"""
  Copyright 2008 Texas A&M University Licensed under the
  Educational Community License, Version 2.0 (the "License"); you may
  not use this file except in compliance with the License. You may
  obtain a copy of the License at
  
  http://www.osedu.org/licenses/ECL-2.0

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS"
  BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
  or implied. See the License for the specific language governing
  permissions and limitations under the License.
"""

import unittest

from datetime import datetime

import zope.interface

from meercat.base.Resource import Resource
from meercat.base.Instance import Instance
from meercat.base.Metadata import Metadata

from meercat.storage.sqlalchemy import SqlAlchemyStorageEngine
from meercat.storage.sqlalchemy import SqlAlchemyStorage

class BaseTest(unittest.TestCase):
    def setUp(self):
        self.se = SqlAlchemyStorageEngine('sqlite:///:memory:')
        self.se.metadata().create_all()
        
        self.generateData()
            
        self.se.session().flush()
        
        self.storage = SqlAlchemyStorage()
        
    
    def generateData(self):
        for t in range(1,3):
            source = u'temporary%s' % (t,)
            
            for i in range(0,10):
                resource = self.se.Resource()
                instance = self.se.Instance(source=source,
                                            identifier=unicode(i))
                
                for j in range(0,5):
                    m = self.se.Metadata(source=source,
                                         format=u'string',
                                         value=u'value %s::%s' % (i,j))
                    m.instance = instance
                
                for j in range(5,10):
                    m = self.se.Metadata(source=u'temporary::second',
                                         format=u'string',
                                         value=u'value %s::%s' % (i,j))
                    m.instance = instance
                
                instance.resource = resource
        

    def testGetInstance(self):
        r = self.storage.getInstances(identifier=u'0',source=u'temporary1')
        
        self.assertEqual(len(r),1)
        self.assertEqual(r[0].getIdentifier(),u'0')
        self.assertEqual(r[0].getSource(),u'temporary1')
        self.assert_(r[0].isActive())
    
    def testGetInstances(self):
        r = self.storage.getInstances(from_date=datetime(2007,1,1),
                                      until_date=datetime.now())
        
        self.assertEqual(len(r),20)
    
    def testGetResource(self):
        r = self.storage.getResources(identifier=1)
        
        self.assertEqual(len(r),1)
        self.assertEqual(r[0].getIdentifier(),1)
        
    
    def testGetResources(self):
        self.assertEqual(len(self.storage.getResources()),20)
        
        self.assertEqual(len(self.storage.getResources(source=u'temporary1')),
                         10)
        
        self.assertEqual(len(self.storage.getResources(from_date=datetime(2007,1,1))),
                         20)
        
        self.assertEqual(len(self.storage.getResources(until_date=datetime(2007,1,1))),
                         0)
        
        self.assertEqual(len(self.storage.getResources(from_date=datetime(2007,1,1),
                                                       until_date=datetime.now())),
                         20)
        
        self.assertEqual(len(self.storage.getResources(offset=10)),10)
        
        self.assertEqual(len(self.storage.getResources(limit=5)),5)
        
        self.assertEqual(len(self.storage.getResources(offset=10,limit=5)),5)
    
    def testInsertAction(self):
        values = [u'value inserted:%s' % x for x in range(0,5)]
        
        i = Instance(source=u'temporary1',
                     identifier=u'insertaction',
                     active=True,
                     metadata=[Metadata(format=u'string',
                                        source=u'temporary1',
                                        value=v) for v in values 
                               ],
                     modified=datetime(2008,1,1,12,0,0))
        
        self.storage.action(i)
        
        results = self.storage.getInstances(identifier=u'insertaction',
                                            source=u'temporary1')
        
        self.assertEqual(len(results),1)
        
        for metadata in results[0]:
            self.assertTrue(metadata.getValue() in values)

    def testUpdateAction(self):
        values = [u'value updated:%s' % x for x in range(0,5)]
        
        i = Instance(source=u'temporary1',
                     identifier=u'3',
                     active=True,
                     metadata=[Metadata(format=u'string',
                                        source=u'temporary1',
                                        value=v) for v in values 
                               ])
        
        self.storage.action(i)
        
        results = self.storage.getInstances(identifier=u'3',
                                            source=u'temporary1')
        
        self.assertEqual(len(results),1)
        
        for metadata in results[0]:
            self.assert_(metadata.getSource() != u'temporary1' or 
                         metadata.getValue() in values,
                         u'source = %s, value=%s' % (metadata.getSource(),
                                                     metadata.getValue()))

    def testMerge(self):
        destination = self.storage.getResources(source=u'temporary1')[0]
        remove = self.storage.getResources(source=u'temporary2',limit=5)
        
        self.storage.merge(destination,remove)
        
        self.assertEqual(len(destination),6,u'Destination should contain 6 instances now')
        
        r = self.storage.getResources()
        
        self.assertEqual(len(r),15)
        
        

def test_suite():
  suite = unittest.TestSuite()
  suite.addTest(unittest.TestLoader().loadTestsFromTestCase(BaseTest))
  return suite

if __name__ == '__main__':
  unittest.TextTestRunner(verbosity=2).run(test_suite())
